package com.gitee.ed.pattern.strategy;

import com.gitee.ed.common.CommonUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * 策略工厂
 * 负责组装和执行策略
 *
 * @author hongda.li
 */
public record StrategyFactory<Context>(List<Strategy<Context>> strategyList) {

    /**
     * 基于优先级注解进行排序 {@link com.gitee.ed.common.Priority}
     *
     * @return 链式调用
     */
    public StrategyFactory<Context> sort() {
        return this.sort(Comparator.comparingInt(strategy -> CommonUtils.parsePriority(strategy.getClass())));
    }

    /**
     * 针对给定的策略排序器，将所有策略实现进行排序
     *
     * @param comparator 自定义策略排序器
     * @return 链式调用
     */
    public StrategyFactory<Context> sort(Comparator<Strategy<Context>> comparator) {
        Objects.requireNonNull(comparator);
        this.strategyList.sort(comparator);
        return this;
    }

    /**
     * 执行第一个符合的策略
     *
     * @param context 上下文
     */
    public void invokeFirst(Context context) {
        this.invokeFirstOrElse(context, null);
    }

    /**
     * 执行第一个符合的策略
     * 若有策略均不支持时，则执行兜底策略
     *
     * @param context         上下文
     * @param defaultStrategy 当所有策略均不支持时的默认兜底策略
     */
    public void invokeFirstOrElse(Context context, Strategy<Context> defaultStrategy) {
        Strategy<Context> find = strategyList.stream()
                .filter(strategy -> strategy.supported(context))
                .findFirst()
                .orElse(defaultStrategy);
        if (find != null && find.supported(context)) {
            find.invoke(context);
        }
    }

    /**
     * 执行所有符合的策略
     *
     * @param context 上下文
     */
    public void invokeMatched(Context context) {
        this.strategyList.stream()
                .filter(strategy -> strategy.supported(context))
                .forEach(strategy -> strategy.invoke(context));
    }
}
